#ifndef __CHANNEL_H__
#define __CHANNEL_H__

#include <sys/epoll.h>
#include "Base/callback.h"
#include "Base/noncopyable.h"
#include "eventloop.h"

namespace tiny_muduo
{
    enum ChannelState
    {
        kNew,
        kAdded,
        kDeleted
    };

    class Channel : public NonCopyable
    {
    public:
        Channel(EventLoop* loop, const int& fd);
        ~Channel();

        void HandleEvent();

        void SetReadCallback(const ReadCallback& callback)
        {
            read_callback_ = callback;
        }

        void SetReadCallback(ReadCallback&& callback)
        {
            read_callback_ = std::move(callback);
        }

        void SetWriteCallback(const WriteCallback& callback)
        {
            write_callback_ = callback;
        }

        void SetWriteCallback(WriteCallback&& callback)
        {
            write_callback_ = std::move(callback);
        }

        void EnableReading()
        {
            events_ |= (EPOLLIN | EPOLLPRI);
            Update();
        }

        void EnableWriting()
        {
            events_ |= EPOLLOUT;
            Update();
        }

        void DisableWriting()
        {
            events_ &= ~EPOLLOUT;
            Update();
        }

        void DisableAll()
        {
            events_ = 0;
            Update();
        }

        void Update()
        {
            loop_->Update(this);
        }

        void SetReceivedEvents(int events)
        {
            recv_events_ = events;
        }

        void SetChannelState(ChannelState state)
        {
            state_ = state;
        }

        inline int fd() { return fd_; }
        inline int events() { return events_; } 
        inline int recv_events() { return recv_events_; }

        inline ChannelState state() { return state_; }
        
        inline bool IsWriting() { return events_ & EPOLLOUT; }
        inline bool IsReading() { return events_ & (EPOLLIN | EPOLLPRI); }
        
    private:
        EventLoop* loop_;
        int fd_;
        int events_;
        int recv_events_;
    
        ChannelState state_;
        ReadCallback read_callback_;
        WriteCallback write_callback_;
    };
}
#endif
